//#include "stdafx.h"
#include "Grid.h"
#include <string.h>
#include <limits.h>
//#include <windows.h>

Grid::Grid()
{
	timed = false;
	pCallBack = 0;
	next = 0;
}

Grid::Grid(Grid * old)
{
	//Grid();
	//timed = false;
	//pCallBack = 0;
	timed = false;
	pCallBack = 0;
	next = 0;
	memcpy(grid, old->grid, ROWS * COLS);
}

Grid::~Grid(void)
{
	if (next) {
		delete next;
		next = 0;
	}

	for (int i=0;i<(int)wordlist.size();i++)
		delete wordlist[i];

	wordlist.clear();
}

void Grid::GetGrid(char * inputgrid)
{
	if (strlen(inputgrid) < ROWS * COLS)
	{
		printf("Invalid input grid.\n");
		return;
	}

	int i=0;
	for (int y=0;y<ROWS;y++)
	{
		for (int x=0;x<COLS;x++)
		{
			if (inputgrid[i] >= 'a' && inputgrid[i] <= 'z')
				inputgrid[i] = toupper(inputgrid[i]);

			if (inputgrid[i] ==  ' ')
				grid[x][y] = 0;
			else
				grid[x][y] = inputgrid[i];

			i++;
		}
	}
}


void Grid::PrintGrid()
{
	//HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
	for (int g=0;g<ROWS;g++)
	{
		for (int r=0;r<COLS;r++)
		{
			//SetConsoleTextAttribute(hStdout, FOREGROUND_BLUE);
			bool isvalid = false;
			for (int i=0;i<wordlen;i++)
			{
				if (r == word[i].x && g == word[i].y)
					isvalid = true;
					//SetConsoleTextAttribute(hStdout, FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED | (FOREGROUND_GREEN * (i == 0)));
			}
			if (grid[r][g])
			{
				if (isvalid)
					printf("%c`", grid[r][g]);
				else
					printf("%c ", grid[r][g]);
			}
			else
				printf("  ");
		}
		printf("\n");
	}
	//SetConsoleTextAttribute(hStdout, 15);
}

int Grid::GetTail()
{
	int x,y,tail = 0;
	for (x=0;x<COLS;x++)
	{
		if ((grid[x][ROWS-1] == 0))
			continue;

		if ((grid[x][ROWS-2] == 0))
			tail++;
		else break;
	}
	for (y=0;y<ROWS;y++)
	{
		if ((grid[COLS-1][y] == 0))
			continue;

		if ((grid[COLS-2][y] == 0))
			tail++;
		else break;
	}
	return tail;
}

int Grid::Letters()
{
	int x,y;
	int letters = 0;

	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (grid[x][y]) letters++;
	}

	return letters;
}


double Grid::Ratio()
{
	int x,y;
	int letcount[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	int numletters = 0;

	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (grid[x][y] < 'A' || grid[x][y] > 'Z') continue;

		letcount[grid[x][y] - 'A']++;
		numletters++;
	}

	if (!numletters) return 0;

	double diff,ret = 0;

	for (int l=0;l<26;l++)
	{
		diff = Dictionary->letprob[l] - ((double)letcount[l] / (double)numletters);
		
		if (diff < 0)
			diff = -diff;
		
		ret += diff;
	}
	return ret;
}

double Grid::Shape()
{
	double ret = ROWS*COLS;
	int x,y;
	for (y=0;y<ROWS;y++)
	{
		for (x=0;x<COLS;x++)
		{
			if (grid[x][y]) break;
		}
		if (x==COLS) continue;

		double get = sqrt((double)((ROWS-y)*(ROWS-y) + (COLS-x)*(COLS-x)));
			//sqrt(((double)(ROWS-y))*((double)(ROWS-y)) + ((double)(COLS-x))*((double)(COLS-x))); what was i thinking?

		if (ret > get)
			ret = get;
	}
	return ret;
}

/*float Grid::Gradient()
{
	int x,y,height,width;

	for (x=0;x<COLS;x++)
	for (y=0;y<ROWS;y++)
	{
		if (grid[x][y] != 0)
		{
			width = COLS - x;
			x = COLS;
			break;
		}
	}
	
	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (grid[x][y] != 0)
		{
			height = ROWS - y;
			y = ROWS;
			break;
		}
	}

	if (width == 0) return 0;

	return (height / (float)width);
}*/

void Grid::FallGrid()
{
	int x,y,fall = 0;

	for (x=COLS-1;x>=0;x--)
	{
		fall = ROWS-1;
		for (y=ROWS-1;y>=0;y--)
		{
			if (grid[x][y] != 0) 
			{
				grid[x][fall] = grid[x][y];
				fall--;
			}
		}
		for (y=fall;y>=0;y--)
			grid[x][y] = 0;
	}

	for (y=ROWS-1;y>=0;y--)
	{
		fall = COLS-1;
		for (x=COLS-1;x>=0;x--)
		{
			if (grid[x][y] != 0) 
			{
				grid[fall][y] = grid[x][y];
				fall--;
			}
		}
		for (x=fall;x>=0;x--)
			grid[x][y] = 0;
	}
}


					 // { 0, 3, 2, 1, 0, 4, 2, 3, 1, 5, 4, 2, 3, 1, 0, 2, 6, 1, 0, 0, 2, 4, 3, 5, 3, 6}; //Puzzle Word
					 // { 0, 2, 2, 1, 0, 3, 1, 3, 2, 5, 4, 4, 2, 1, 0, 2, 6, 0, 0, 0, 1, 3, 3, 5, 3, 6 }; //Word Soup
					 // { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,  R, S, T, U, V, W, X, Y, Z }
//int valuearray[26] =	{ 1, 4, 3, 2, 1, 5, 3, 4, 2, 8, 5, 3, 4, 2, 1, 3, 10, 2, 1, 1, 3, 5, 4, 8, 4, 10 };	//Puzzle word		
//int pointarray[26] =	{ 1, 3, 3, 2, 1, 4, 2, 4, 3, 8, 5, 5, 3, 2, 1, 3, 10, 1, 1, 1, 2, 4, 4, 8, 4, 10 }; //Word Soup

/*int Grid::GetPoints(char letter)//, bool false)
{
	if (letter >= 'A' && letter <= 'Z') return pointarray[letter - 'A'];

	return 0;
	switch (letter) {
		case 'Q':
		case 'Z':
			return (10 + timed*100);
		case 'J':
		case 'X':
			return (8 + timed*100);
		case 'F':
		case 'K':
			return 5;
		case 'B':
		case 'H':
		case 'M': 
		case 'V':
		case 'W':
		case 'Y':
			return 4;
		case 'C':
		case 'G':
		case 'L':
		case 'P':
		case 'U':
			return 3;
		case 'D':
		case 'I':
		case 'N':
		case 'R':
			return 2;
		case 'A':
		case 'E':
		case 'O':
		case 'T':
		case 'S':
			return 1;
		default:
			return 0;
	}
}*/

bool Grid::IsValid(int x, int y)
{
	if (x < 0 || x >= COLS || y < 0 || y >= ROWS || grid[x][y] < 'A' || grid[x][y] > 'Z')
		return false;
	for (int i=0;i<length;i++)
	{
		if (x == current[i].x && y == current[i].y)
			return false;
	}
	return true;
}


void Grid::ScanLetter(DictionaryNode * parse, int x, int y)
{
	if (IsValid(x,y))
	{
		DictionaryNode * Next = Dictionary->GiveLetter(parse, grid[x][y]);
		if (Next)
		{
			if (Next->isword && length >= 2)
			{
				words++;
				current[length].x = x;
				current[length].y = y;
				current[length].letter = grid[x][y];
				if (pCallBack) {
					length++;
					pCallBack(this);
					length--;
				}
			}

			ScanWord(Next,x,y);
		}
	}
}

void Grid::ScanWord(DictionaryNode * parse, int x, int y)
{
	current[length].x = x;
	current[length].y = y;
	current[length].letter = grid[x][y];

	length += 1;
	if (length >= 28) return;

	int nx,ny;

	nx = x + 1;	ny = y + 1; 
	ScanLetter(parse,nx,ny);
	nx = x + 1;	ny = y; 
	ScanLetter(parse,nx,ny);
	nx = x + 1;	ny = y - 1;
	ScanLetter(parse,nx,ny);
	nx = x;		ny = y + 1;
	ScanLetter(parse,nx,ny);
	nx = x;		ny = y - 1;
	ScanLetter(parse,nx,ny);
	nx = x - 1;	ny = y;
	ScanLetter(parse,nx,ny);
	nx = x - 1;	ny = y + 1;
	ScanLetter(parse,nx,ny);
	nx = x - 1;	ny = y - 1;
	ScanLetter(parse,nx,ny);

	length -= 1;
}

void Grid::FindWord(int x, int y)
{	
	length = 0;
	DictionaryNode * Node = Dictionary->Start();

	Node = Dictionary->GiveLetter(Node, grid[x][y]);

	if (Node)
		ScanWord(Node, x,y);
}

//UOIIESLNEJSWTAVHPPTEZKTOOANASAORFMIRAILOCLBTIEMBTIAEOYVNIJUDDPAERUNPJOTBBEEJSREZWMURWLTEIRABGOITNBNWLRUASIETDIHEDFAIO

void Grid::ApplyWord(struct pos * word, int length)
{
	for (int b=0;b<length;b++)
	{
		//printf("%c %d %d\n", newgrid.word[b].letter, newgrid.word[b].x, newgrid.word[b].y);
		grid[word[b].x][word[b].y] = 0;
	}
}

void Grid::FindWords()
{
	words = 0;
	mostvalue = INT_MIN;
	int x,y;
	
	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (grid[x][y] == 0) continue;

		FindWord(x,y);
	}

	if (!words) wordlen = 0;
}
